#include "mind_vision.hpp"

MindVision::MindVision():iStatus(-1)
{
    total_frame = vector(CAMERA_NUM, 0);
    capture_frame = vector(CAMERA_NUM, 0);
    lost_frame = vector(CAMERA_NUM, 0);
    camera_init();
}

MindVision::~MindVision(){
    for(int i = 0; i < CAMERA_NUM; i++){
        // 关闭相机
        CameraUnInit(hCamera[i]);
        // 注意，现反初始化后再free
        free(g_pRgbBuffer[i]);
    }
}

/**
 * @brief 初始化相机以及参数调整
 * @param 
 * @return 
 * @details 
*/
void MindVision::camera_init(){
    // 初始化SDK
	CameraSdkInit(1);
    // 枚举设备，并建立设备列表
    iStatus = CameraEnumerateDevice(tCameraEnumList, &iCameraCounts);
	cout << "摄像头连接数量: " << iCameraCounts << endl;
    // 没有连接设备
    if(iCameraCounts == 0){
        cout << "摄像头未连接" << endl;
        return;
    }
	// 相机初始化。初始化成功后，才能调用任何其他相机相关的操作接口
    for(int i = 0; i < CAMERA_NUM; i++){
        iStatus = CameraInit(&tCameraEnumList[i], -1, -1, &hCamera[i]);
        // 初始化失败则退出
        if(iStatus != CAMERA_STATUS_SUCCESS){
            cout << "摄像头初始化失败，状态码：" << iStatus << endl;
            return;
        }
        // 获得相机的特性描述结构体。该结构体中包含了相机可设置的各种参数的范围信息。决定了相关函数的参数
        CameraGetCapability(hCamera[i], &tCapability[i]);
        // 手动分配图像内存，结束记得free释放
        g_pRgbBuffer[i] = (unsigned char*)malloc(tCapability[i].sResolutionRange.iHeightMax * tCapability[i].sResolutionRange.iWidthMax * 3);
        // 让SDK进入工作模式，开始接收来自相机发送的图像数据。如果当前相机是触发模式，则需要接收到触发帧以后才会更新图像。
	    CameraPlay(hCamera[i]);
        // 区分黑白和彩色摄像头，设置不同图像格式
        if(tCapability[i].sIspCapacity.bMonoSensor){
            CameraSetIspOutFormat(hCamera[i], CAMERA_MEDIA_TYPE_MONO8);
        }else{
            CameraSetIspOutFormat(hCamera[i], CAMERA_MEDIA_TYPE_BGR8);
        }
        //曝光模式
        int mode = false;
        CameraSetAeState(hCamera[i], false);
        CameraGetAeState(hCamera[i], &mode);
        cout << "mode: " << mode << endl;
        // 相机帧率
        int speed = 2;
        CameraSetFrameSpeed(hCamera[i], 1);
        CameraGetFrameSpeed(hCamera[i], &speed);
        cout << "speed: " << speed << endl;
        int rate = 0;
        CameraSetFrameRate(hCamera[i], 60);
        CameraGetFrameRate(hCamera[i], &rate);
        cout << "rate: " << rate << endl;
        // 自动曝光目标值
        int ae_target = 40;
        CameraSetAeTarget(hCamera[i], 120);
        CameraGetAeTarget(hCamera[i], &ae_target);
        cout << "ae_target: " << ae_target << endl;
        // 曝光时间，增益
        double extime = 0.0;
        CameraSetExposureTime(hCamera[i], 13000);
        CameraGetExposureTime(hCamera[i], &extime);
        cout << "ExposureTime: " << extime << endl;
        int gain = 0;
        CameraSetAnalogGain(hCamera[i], 16);
        CameraGetAnalogGain(hCamera[i], &gain);
        cout << "gain: " << gain << endl;
        float gainx = 0.0;
        CameraSetAnalogGainX(hCamera[i], 2);
        CameraGetAnalogGainX(hCamera[i], &gainx);
        cout << "gainx: " << gainx << endl;
        // double mintime, maxtime = 0.0;
        // CameraGetAeExposureRange(hCamera[i], &mintime ,&maxtime);
        // cout << "mintime: " << mintime << "maxtime: " << maxtime << endl;
        // 打印相机特性参数
        // print_info(&tCapability[i]);
        int min_gain, max_gain = 0;
        CameraGetAeAnalogGainRange(hCamera[i], &min_gain, &max_gain);
        cout << "min_gain: " << min_gain << "max_gain: " << max_gain << endl;
        float min_gainx, max_gainx, step_gainx = 0;
        CameraGetAnalogGainXRange(hCamera[i], &min_gainx, &max_gainx, &step_gainx);
        cout << "min_gainx: " << min_gainx << "max_gainx: " << max_gainx << "step_gainx: " << step_gainx << endl;

    }
    
}

/**
 * @brief 获取图像并转化成Mat格式
 * @param 
 * @return 
 * @details 
*/
void MindVision::frame_update(){
    TickMeter tk;
    for(int i = 0; i < CAMERA_NUM; i++){
        if(CameraGetImageBuffer(hCamera[i],&sFrameInfo[i],&pbyBuffer[i],1000) == CAMERA_STATUS_SUCCESS){
		    // 将获得的相机原始输出图像数据进行处理，叠加饱和度、颜色增益和校正、降噪等处理效果
            tk.reset();
		    tk.start();
			CameraImageProcess(hCamera[i], pbyBuffer[i], g_pRgbBuffer[i],&sFrameInfo[i]);
            tk.stop();
		    // cout << "------------------------时间:" << tk.getTimeMilli() << endl;
		    // 将图像转换成Mat格式
		    rgb_frame[i] = Mat(
					Size(sFrameInfo[i].iWidth,sFrameInfo[i].iHeight), 
					sFrameInfo[i].uiMediaType == CAMERA_MEDIA_TYPE_MONO8 ? CV_8UC1 : CV_8UC3,
					g_pRgbBuffer[i]
					);

            //在成功调用CameraGetImageBuffer后，必须调用CameraReleaseImageBuffer来释放获得的buffer。
			//否则再次调用CameraGetImageBuffer时，程序将被挂起一直阻塞，直到其他线程中调用CameraReleaseImageBuffer来释放了buffer
			CameraReleaseImageBuffer(hCamera[i],pbyBuffer[i]);

		}
    }
}

/**
 * @brief 打印相机基本参数
 * @param tCapability 初始化中获取的设备信息结构体
 * @return 
 * @details 
*/
void MindVision::print_info(tSdkCameraCapbility* tCapability){
    cout << "帧速率个数: " << tCapability->iFrameSpeedDesc
    << "当前帧速率编号: " << (++(tCapability->pFrameSpeedDesc))->iIndex
    << "描述: " << tCapability->pFrameSpeedDesc->acDescription << endl;
    cout << "skip模式: " << tCapability->sResolutionRange.uSkipModeMask 
    << "求和模式: " << tCapability->sResolutionRange.uBinSumModeMask
    << "求均值模式: " << tCapability->sResolutionRange.uBinAverageModeMask << endl;
}

/**
 * @brief 相机采集的fps显示回调函数
 * @param hCamera 相机句柄
 * @return 
 * @details 
*/
void MindVision::print_fps_callback(CameraHandle* hCamera){
    while(1){
        this_thread::sleep_for(chrono::milliseconds(1000));
        // 显示帧率
        cout << "实时帧率: " << fps_count << endl;
        fps_count = 0;
        // 显示相机信息
        // tSdkFrameStatistic framesta;
        // for(int i = 0; i < CAMERA_NUM; i++){
        //     CameraGetFrameStatistic(*hCamera + i, &framesta);
        //     cout << "每秒总帧数: " << framesta.iTotal - total_frame[i] 
        //         << " 有效帧数: " << framesta.iCapture - capture_frame[i] 
        //         << " 丢帧数: " << framesta.iLost - lost_frame[i] << endl;
        //     total_frame[i] = framesta.iTotal;
        //     capture_frame[i] = framesta.iCapture;
        //     lost_frame[i] = framesta.iLost;
        //     // 曝光时间，增益
        //     double extime = 0.0;
        //     CameraGetExposureTime(*hCamera + i, &extime);
        //     cout << "ExposureTime: " << extime << endl;
        //     int gain = 0;
        //     CameraGetAnalogGain(*hCamera + i, &gain);
        //     cout << "gain: " << gain << endl;
        //     float gainx = 0.0;
        //     CameraGetAnalogGainX(*hCamera + i, &gainx);
        //     cout << "gainx: " << gainx << endl;
        // }
    }
}